Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit 637a44ad70fe9390ad646ec09ca38ffa04200764


Parents : 4d94399
Author : Mark Qvist <mark@adepta.io>
Date : 2018-06-20T08:45:11+02:00

EEPROM validation and config util compat

Changes

5 files changed, 256 insertions(+), 55 deletions(-)

M Config.h +16 -4
D EEPROM.cpp -36
M Framing.h +19 -11
M Utilities.cpp +158 -1

Diff

diff --git a/Config.h b/Config.h
index a8aeca6..ec87d76 100644
--- a/Config.h
+++ b/Config.h
@@ -1,13 +1,14 @@
+#include "ROM.h"
+
#ifndef CONFIG_H
#define CONFIG_H
+ #define MAJ_VERS 0x01
+ #define MIN_VERS 0x03
+
#define MCU_328P 0x90
#define MCU_1284P 0x91
- #define PRODUCT_RNODE 0x03
- #define MODEL_A4 0xA4
- #define MODEL_A9 0xA9
-
#if defined(__AVR_ATmega328P__)
#define MCU_VARIANT MCU_328P
#warning "Firmware is being compiled for atmega328p based boards"
@@ -33,6 +34,9 @@
#define FLOW_CONTROL_ENABLED true
#define QUEUE_SIZE 0
+
+ #define EEPROM_SIZE 512
+ #define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
#endif
#if MCU_VARIANT == MCU_1284P
@@ -44,8 +48,13 @@
#define FLOW_CONTROL_ENABLED true
#define QUEUE_SIZE 24
+
+ #define EEPROM_SIZE 4096
+ #define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
#endif
+ #define eeprom_addr(a) (a+EEPROM_OFFSET)
+
// MCU independent configuration parameters
const long serial_baudrate = 115200;
const int rssi_offset = 164;
@@ -62,6 +71,9 @@
// Operational variables
bool radio_locked = true;
bool radio_online = false;
+ bool hw_ready = false;
+ uint8_t model = 0x00;
+ uint8_t hwrev = 0x00;
int last_rssi = -164;
size_t read_len = 0;

diff --git a/EEPROM.cpp b/EEPROM.cpp
deleted file mode 100644
index b1990c1..0000000
--- a/EEPROM.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <Arduino.h>
-#include <EEPROM.h>
-#include "Config.h"
-#include "Framing.h"
-
-#define ADDR_PRODUCT 0x00
-#define ADDR_MODEL 0x01
-#define ADDR_HW_REV 0x02
-#define ADDR_SERIAL 0x03
-#define ADDR_MADE 0x06
-#define ADDR_CHKSUM 0x0A
-#define ADDR_SIGNATURE 0x1A
-#define ADDR_INFO_LOCK 0x9A
-#define INFO_LOCK_BYTE 0x73
-
-#define ADDR_CONF_SF 0x74
-#define ADDR_CONF_CR 0x75
-#define ADDR_CONF_TXP 0x76
-#define ADDR_CONF_BW 0x77
-#define ADDR_CONF_FREQ 0x7B
-#define ADDR_CONF_OK 0x7F
-#define CONF_OK_BYTE 0x73
-
-void eeprom_dump_info() {
- for (int addr = ADDR_PRODUCT; addr <= ADDR_INFO_LOCK; addr++) {
- uint8_t rom_byte = EEPROM.read(addr);
- Serial.write(rom_byte);
- }
-}
-
-void eeprom_dump_config() {
- for (int addr = ADDR_CONF_SF; addr <= ADDR_CONF_OK; addr++) {
- uint8_t rom_byte = EEPROM.read(addr);
- Serial.write(rom_byte);
- }
-}
\ No newline at end of file

diff --git a/Framing.h b/Framing.h
index af81042..eeebdf5 100644
--- a/Framing.h
+++ b/Framing.h
@@ -12,8 +12,10 @@
#define CMD_BANDWIDTH 0x02
#define CMD_TXPOWER 0x03
#define CMD_SF 0x04
- #define CMD_RADIO_STATE 0x05
- #define CMD_RADIO_LOCK 0x06
+ #define CMD_CR 0x05
+ #define CMD_RADIO_STATE 0x06
+ #define CMD_RADIO_LOCK 0x07
+ #define CMD_DETECT 0x08
#define CMD_READY 0x0F
#define CMD_STAT_RX 0x21
@@ -22,23 +24,29 @@
#define CMD_BLINK 0x30
#define CMD_RANDOM 0x40
- #define CMD_INFO_READ 0x50
- #define CMD_INFO_WRITE 0x51
- #define CMD_CONF_READ 0x52
- #define CMD_CONF_WRITE 0x53
+ #define CMD_FW_VERSION 0x50
+ #define CMD_ROM_READ 0x51
+ #define CMD_ROM_WRITE 0x52
+ #define CMD_CONF_SAVE 0x53
+ #define CMD_UNLOCK_ROM 0x59
+ #define ROM_UNLOCK_BYTE 0xF8
+
+ #define DETECT_REQ 0x73
+ #define DETECT_RESP 0x46
#define RADIO_STATE_OFF 0x00
#define RADIO_STATE_ON 0x01
- #define CMD_ERROR 0x90
- #define ERROR_INITRADIO 0x01
- #define ERROR_TXFAILED 0x02
-
#define NIBBLE_SEQ 0xF0
#define NIBBLE_FLAGS 0x0F
#define FLAG_SPLIT 0x01
#define SEQ_UNSET 0xFF
+ #define CMD_ERROR 0x90
+ #define ERROR_INITRADIO 0x01
+ #define ERROR_TXFAILED 0x02
+ #define ERROR_EEPROM_LOCKED 0x03
+
// Serial framing variables
size_t frame_len;
bool IN_FRAME = false;
@@ -57,7 +65,7 @@ All: 0xc00119d21b80c00200005140c00308c00407c0
Radio on 0xc00501c0
-Config+on 0xc00119d21b80c00200005140c00308c00407c00501c0
+Config+on 0xc00119d21b80c00200005140c00301c00407c00601c0
c1 = self.bandwidth >> 24

diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino
index 5d1c851..9a9e2a6 100644
--- a/RNode_Firmware.ino
+++ b/RNode_Firmware.ino
@@ -2,7 +2,6 @@
#include <LoRa.h>
#include "Config.h"
#include "Framing.h"
-#include "EEPROM.cpp"
#include "Utilities.cpp"
void setup() {
@@ -25,12 +24,15 @@ void setup() {
// Set chip select, reset and interrupt
// pins for the LoRa module
LoRa.setPins(pin_cs, pin_reset, pin_dio);
+
+ // Validate board health, EEPROM and config
+ validateStatus();
}
bool startRadio() {
update_radio_lock();
if (!radio_online) {
- if (!radio_locked) {
+ if (!radio_locked && hw_ready) {
if (!LoRa.begin(lora_freq)) {
// The radio could not be started.
// Indicate this failure over both the
@@ -280,6 +282,18 @@ void serialCallback(uint8_t sbyte) {
setSpreadingFactor();
kiss_indicate_spreadingfactor();
}
+ } else if (command == CMD_CR) {
+ if (sbyte == 0xFF) {
+ kiss_indicate_codingrate();
+ } else {
+ int cr = sbyte;
+ if (cr < 5) cr = 5;
+ if (cr > 8) cr = 8;
+
+ lora_cr = cr;
+ setCodingRate();
+ kiss_indicate_codingrate();
+ }
} else if (command == CMD_RADIO_STATE) {
if (sbyte == 0xFF) {
kiss_indicate_radiostate();
@@ -303,6 +317,33 @@ void serialCallback(uint8_t sbyte) {
led_indicate_info(sbyte);
} else if (command == CMD_RANDOM) {
kiss_indicate_random(getRandom());
+ } else if (command == CMD_DETECT) {
+ if (sbyte == DETECT_REQ) {
+ kiss_indicate_detect();
+ }
+ } else if (command == CMD_UNLOCK_ROM) {
+ if (sbyte == ROM_UNLOCK_BYTE) {
+ unlock_rom();
+ }
+ } else if (command == CMD_ROM_READ) {
+ kiss_dump_eeprom();
+ } else if (command == CMD_ROM_WRITE) {
+ if (sbyte == FESC) {
+ ESCAPE = true;
+ } else {
+ if (ESCAPE) {
+ if (sbyte == TFEND) sbyte = FEND;
+ if (sbyte == TFESC) sbyte = FESC;
+ ESCAPE = false;
+ }
+ cbuf[frame_len++] = sbyte;
+ }
+
+ if (frame_len == 2) {
+ eeprom_write(cbuf[0], cbuf[1]);
+ }
+ } else if (command == CMD_FW_VERSION) {
+ kiss_indicate_version();
}
}
}
@@ -344,6 +385,20 @@ void checkModemStatus() {
}
}
+void validateStatus() {
+ if (eeprom_lock_set()) {
+ if (eeprom_product_valid() && eeprom_model_valid() && eeprom_hwrev_valid()) {
+ if (eeprom_checksum_valid()) {
+ hw_ready = true;
+ }
+ } else {
+ hw_ready = false;
+ }
+ } else {
+ hw_ready = false;
+ }
+}
+
void loop() {
if (radio_online) {
checkModemStatus();
@@ -362,7 +417,12 @@ void loop() {
}
}
} else {
- led_indicate_standby();
+ if (hw_ready) {
+ led_indicate_standby();
+ } else {
+ led_indicate_not_ready();
+ stopRadio();
+ }
}
if (Serial.available()) {

diff --git a/Utilities.cpp b/Utilities.cpp
index 29d9639..7417086 100644
--- a/Utilities.cpp
+++ b/Utilities.cpp
@@ -1,7 +1,10 @@
#include <Arduino.h>
+#include <EEPROM.h>
#include <LoRa.h>
+#include "ROM.h"
#include "Config.h"
#include "Framing.h"
+#include "MD5.h"
void led_rx_on() { digitalWrite(pin_led_rx, HIGH); }
void led_rx_off() { digitalWrite(pin_led_rx, LOW); }
@@ -68,6 +71,22 @@ void led_indicate_standby() {
}
led_standby_value += led_standby_direction;
analogWrite(pin_led_rx, led_standby_value);
+ digitalWrite(pin_led_tx, 0);
+ }
+}
+
+void led_indicate_not_ready() {
+ led_standby_ticks++;
+ if (led_standby_ticks > led_standby_wait) {
+ led_standby_ticks = 0;
+ if (led_standby_value <= led_standby_min) {
+ led_standby_direction = 1;
+ } else if (led_standby_value >= led_standby_max) {
+ led_standby_direction = -1;
+ }
+ led_standby_value += led_standby_direction;
+ analogWrite(pin_led_tx, led_standby_value);
+ digitalWrite(pin_led_rx, 0);
}
}
@@ -132,6 +151,13 @@ void kiss_indicate_spreadingfactor() {
Serial.write(FEND);
}
+void kiss_indicate_codingrate() {
+ Serial.write(FEND);
+ Serial.write(CMD_CR);
+ Serial.write((uint8_t)lora_cr);
+ Serial.write(FEND);
+}
+
void kiss_indicate_txpower() {
Serial.write(FEND);
Serial.write(CMD_TXPOWER);
@@ -173,6 +199,21 @@ void kiss_indicate_ready() {
Serial.write(FEND);
}
+void kiss_indicate_detect() {
+ Serial.write(FEND);
+ Serial.write(CMD_DETECT);
+ Serial.write(DETECT_RESP);
+ Serial.write(FEND);
+}
+
+void kiss_indicate_version() {
+ Serial.write(FEND);
+ Serial.write(CMD_FW_VERSION);
+ Serial.write(MAJ_VERS);
+ Serial.write(MIN_VERS);
+ Serial.write(FEND);
+}
+
bool isSplitPacket(uint8_t header) {
return (header & FLAG_SPLIT);
}
@@ -197,7 +238,10 @@ void setCodingRate() {
}
void setTXPower() {
- if (radio_online) LoRa.setTxPower(lora_txp);
+ if (radio_online) {
+ if (model == MODEL_A4) LoRa.setTxPower(lora_txp, PA_OUTPUT_RFO_PIN);
+ if (model == MODEL_A9) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
+ }
}
@@ -235,3 +279,116 @@ uint8_t getRandom() {
}
}
+bool eeprom_info_locked() {
+ uint8_t lock_byte = EEPROM.read(eeprom_addr(ADDR_INFO_LOCK));
+ if (lock_byte == INFO_LOCK_BYTE) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void eeprom_dump_info() {
+ for (int addr = ADDR_PRODUCT; addr <= ADDR_INFO_LOCK; addr++) {
+ uint8_t byte = EEPROM.read(eeprom_addr(addr));
+ escapedSerialWrite(byte);
+ }
+}
+
+void eeprom_dump_config() {
+ for (int addr = ADDR_CONF_SF; addr <= ADDR_CONF_OK; addr++) {
+ uint8_t byte = EEPROM.read(eeprom_addr(addr));
+ escapedSerialWrite(byte);
+ }
+}
+
+void eeprom_dump_all() {
+ for (int addr = 0; addr < EEPROM_RESERVED; addr++) {
+ uint8_t byte = EEPROM.read(eeprom_addr(addr));
+ escapedSerialWrite(byte);
+ }
+}
+
+void kiss_dump_eeprom() {
+ Serial.write(FEND);
+ Serial.write(CMD_ROM_READ);
+ eeprom_dump_all();
+ Serial.write(FEND);
+}
+
+void eeprom_write(uint8_t addr, uint8_t byte) {
+ if (!eeprom_info_locked() && addr >= 0 && addr < EEPROM_RESERVED) {
+ EEPROM.update(eeprom_addr(addr), byte);
+ } else {
+ kiss_indicate_error(ERROR_EEPROM_LOCKED);
+ }
+}
+
+void eeprom_erase() {
+ for (int addr = 0; addr < EEPROM_RESERVED; addr++) {
+ EEPROM.update(eeprom_addr(addr), 0xFF);
+ }
+ while (true) { led_tx_on(); led_rx_off(); }
+}
+
+bool eeprom_lock_set() {
+ if (EEPROM.read(eeprom_addr(ADDR_INFO_LOCK)) == INFO_LOCK_BYTE) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool eeprom_product_valid() {
+ if (EEPROM.read(eeprom_addr(ADDR_PRODUCT)) == PRODUCT_RNODE) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool eeprom_model_valid() {
+ model = EEPROM.read(eeprom_addr(ADDR_MODEL));
+ if (model == MODEL_A4 || model == MODEL_A9) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool eeprom_hwrev_valid() {
+ hwrev = EEPROM.read(eeprom_addr(ADDR_HW_REV));
+ if (hwrev != 0x00 && hwrev != 0xFF) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool eeprom_checksum_valid() {
+ char *data = (char*)malloc(CHECKSUMMED_SIZE);
+ for (uint8_t i = 0; i < CHECKSUMMED_SIZE; i++) {
+ char byte = EEPROM.read(eeprom_addr(i));
+ data[i] = byte;
+ }
+
+ unsigned char *hash = MD5::make_hash(data, CHECKSUMMED_SIZE);
+ bool checksum_valid = true;
+ for (uint8_t i = 0; i < 16; i++) {
+ uint8_t stored_chk_byte = EEPROM.read(eeprom_addr(ADDR_CHKSUM+i));
+ uint8_t calced_chk_byte = (uint8_t)hash[i];
+ if (stored_chk_byte != calced_chk_byte) {
+ checksum_valid = false;
+ }
+ }
+
+ free(hash);
+ free(data);
+ return checksum_valid;
+}
+
+void unlock_rom() {
+ led_indicate_error(50);
+ eeprom_erase();
+}
+


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────